/*
* Copyright 2011 Pavel Kozhin 
*
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
* http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed  under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License.
*
* Author: Pavel Kozhin.
*/
package org.etherframework.core.module
{
	import flash.errors.IllegalOperationError;
	
	import org.etherframework.IEther;
	import org.etherframework.common.IDetachable;
	import org.etherframework.common.IStatefulDestroyable;
	import org.etherframework.core.IModule;
	import org.etherframework.core.bridge.ObjectController;
	import org.etherframework.core.bridge.Controllers;
	import org.etherframework.core.bridge.IBridge;
	import org.etherframework.core.bridge.IBridgeFacades;
	import org.etherframework.core.bridge.IObjectController;
	import org.etherframework.core.utils.Dispatcher;
	import org.etherframework.core.utils.utilsClasses.ListenerInfo;

	[ExcludeClass]
	public final class ModuleController extends ObjectController
	{
		private var _target:IModule;
		private var _bridge:IBridge;
		private var _ether:IEther;
		private var _dispatcher:Dispatcher;
		private var _controllers:Controllers;
		private var _listenerInfo:Vector.<ListenerInfo>;
		
		public function ModuleController(target:IModule, ether:IEther, bridge:IBridge)
		{
			super(target, ether, bridge.facade);
			
			_target = target;
			_bridge = bridge;
			_ether = ether;
			_dispatcher = _bridge.dispatcher;
			_controllers = bridge.controllers;
		}
		
		override public function attach():void
		{
			if (!detached || destroyed)
				throw new IllegalOperationError("IController can not be attached.");
			
			if (_bridge is IDetachable)
				IDetachable(_bridge).attach();
			
			if (_listenerInfo)
			{
				_dispatcher.listenInfo(_ether, _listenerInfo);
				_listenerInfo = null;
			}
			
			const scope:Object = this;
			
			_controllers.walk(function(item:IObjectController):void
			{
				if (item != scope)
				{
					item.attach();
					item.detached = false;
				}
			});
		}
		
		override public function detach():void
		{
			if (detached || destroyed)
				throw new IllegalOperationError("IController can not be detached.");
			
			if (_bridge is IDetachable)
				IDetachable(_bridge).detach();
			
			_listenerInfo = _dispatcher.unlistenAll(_ether);
			
			const scope:Object = this;
			
			_controllers.walk(function(item:IObjectController):void
			{
				if (item != scope)
				{
					item.detach();
					item.detached = true;
				}
			});
		}
		
		override public function destroy():void
		{
			if (destroyed)
				throw new IllegalOperationError("IController is already destroyed.");
			
			if (_ether)
				_dispatcher.unlistenAll(_ether);
			
			const scope:Object = this;
			
			_controllers.walk(function(item:IObjectController):void
			{
				if (item != scope)
				{
					item.destroy();
					item.destroyed = true;
				}
			});
			
			if (_target is IStatefulDestroyable)
			{
				IStatefulDestroyable(_target).destroy();
				IStatefulDestroyable(_target).destroyed = true;
			}
			
			if (_bridge is IStatefulDestroyable)
			{
				IStatefulDestroyable(_bridge).destroy();
				IStatefulDestroyable(_bridge).destroyed = true;
			}
			
			_controllers.removeController(this);
			
			_target = null;
			_bridge = null;
			_ether = null;
			_dispatcher = null;
			_listenerInfo = null;
			_controllers = null;
		}
	}
}